package ar.com.gals.service;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import ar.com.gals.error.GalsException;
import ar.com.gals.repository.AbstractRepository;


public abstract class AbstractService<T> {
	
	@SuppressWarnings("deprecation")
	private static SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
	
	protected Class<T> domain;
	
	protected Session session;
	
	protected Transaction transaction;
		
	
	public AbstractService() {
		this.buildSession();
	}

	@SuppressWarnings("all")
	protected void buildSession() {
		this.session = sessionFactory.getCurrentSession();
	}
	
	protected void beginTransaction() {
		if(this.transaction == null)
			this.buildSession();
		
		this.transaction = this.session.beginTransaction();
	}
	
	protected void commit() {
		this.transaction.commit();
		this.transaction = null;
	}
	
	protected void rollback() {
		this.transaction.rollback();
		this.transaction = null;
	}
		
	
	public T getById(int id) throws GalsException {
		
		T object = null; 
		
		try
		{
			this.beginTransaction();
			
			object = (T) new AbstractRepository<T>(this.session, this.domain).getById(id);
			
			this.commit();
		}
		catch(Exception e) {
			
			this.rollback();
			
			throw new GalsException(e.getMessage());
		}
		
		return object;
	}
	
	
	public List<T> getAll() throws GalsException {
		
		List<T> list = new ArrayList<T>();
		
		try
		{
			this.beginTransaction();
		
			list = (List<T>) new AbstractRepository<T>(this.session, this.domain).getAll();
			
			this.commit();
		}
		catch(Exception e) {
			
			this.rollback();
			
			throw new GalsException(e.getMessage());
		}
		
		return list;
	}
	
	
	protected List<T> getAllOrderBy(String property) throws GalsException {
		
		List<T> list = new ArrayList<T>();
		
		try
		{
			this.beginTransaction();
		
			list = (List<T>) new AbstractRepository<T>(this.session, this.domain).getAllOrderBy(property);
			
			this.commit();
		}
		catch(Exception e) {
			
			this.rollback();
			
			throw new GalsException(e.getMessage());
		}
		
		return list;
	}
	
	
	protected List<T> getAllLimit(int limit) throws GalsException {
		
		List<T> list = new ArrayList<T>();
		
		try
		{
			this.beginTransaction();
		
			list = (List<T>) new AbstractRepository<T>(this.session, this.domain).getAllLimit(limit);
			
			this.commit();
		}
		catch(Exception e) {
			
			this.rollback();
			
			throw new GalsException(e.getMessage());
		}
		
		return list;
	}
	

	public void create(T t) throws GalsException {

		try
		{
			this.beginTransaction();
			
			this.executeCreate(t);
		
			this.commit();
		}
		catch(GalsException ge) {
			
			this.rollback();
			
			throw ge;
		}
		catch(Exception e) {
			
			this.rollback();
			
			throw new GalsException(e.getMessage());
		}
	}

	
	protected void executeCreate(T t) throws GalsException {
		
		new AbstractRepository<T>(this.session, this.domain).create(t);
	}
	
	
	public void update(T t) throws GalsException {

		try
		{
			this.beginTransaction();
			
			this.executeUpdate(t);
		
			this.commit();
		}
		catch(GalsException ge) {
			
			this.rollback();
			
			throw ge;
		}
		catch(Exception e) {
			
			this.rollback();
			
			throw new GalsException(e.getMessage());
		}
	}

	
	protected void executeUpdate(T t) throws GalsException {
		
		new AbstractRepository<T>(this.session, this.domain).update(t);
	}
	
	
	public void delete(T t) throws GalsException {

		try
		{
			this.beginTransaction();
			
			this.executeDelete(t);
		
			this.commit();
		}
		catch(GalsException ge) {
			
			this.rollback();
			
			throw ge;
		}
		catch(Exception e) {
			
			this.rollback();
			
			throw new GalsException(e.getMessage());
		}
	}

	protected void executeDelete(T t) throws GalsException {
		
		new AbstractRepository<T>(this.session, this.domain).delete(t);
	}
}
